home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / irit / overload.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-30  |  26.7 KB  |  617 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d (not only polygonal) solid modeller.             *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. ******************************************************************************
  6. *   Module to handle overloaded operators for the input parser module.         *
  7. * Note this module should be accessed by Input Parser only (InptPrsr.c).     *
  8. *****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <math.h>
  13. #include <string.h>
  14. #include "program.h"
  15. #include "allocate.h"
  16. #include "attribut.h"
  17. #include "booleang.h"
  18. #include "freeform.h"
  19. #include "geomat3d.h"
  20. #include "inptprsg.h"
  21. #include "inptprsl.h"
  22. #include "objects.h"
  23. #include "overload.h"
  24.  
  25. /* The following table help to decide if the operand are legal for the given */
  26. /* operator. 5 entries for PLUS, MINUS, MULT, DIV, POWER. Each entry is a    */
  27. /* square matrix of number of object types by number of object types:         */
  28.  
  29. static IritExprType OverLoadDiadicTable[5][11][11] =
  30. /*    POLY_EXPR     NUMERIC_EXPR  POINT_EXPR    VECTOR_EXPR  PLANE_EXPR  MATRIX_EXPR  CURVE_EXPR  SURFACE_EXPR   STRING_EXPR  OLST_EXPR    CTLPT_EXPR */
  31. { { /* PLUS */
  32.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  33.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       STRING_EXPR, NO_EXPR,     NO_EXPR },
  34.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR,  VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  35.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR,  VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  36.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  37.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    MATRIX_EXPR, NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  38.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,       CURVE_EXPR, NO_EXPR,       NO_EXPR,     NO_EXPR,     CURVE_EXPR },
  39.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  40.     { NO_EXPR,   STRING_EXPR,  NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       STRING_EXPR, NO_EXPR,     NO_EXPR },
  41.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     OLST_EXPR,   NO_EXPR },
  42.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     CURVE_EXPR, NO_EXPR,       NO_EXPR,     NO_EXPR,     CURVE_EXPR } },
  43.  
  44.   { /* MINUS */
  45.     { POLY_EXPR, NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  46.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,      NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  47.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR,  VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  48.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR,  VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  49.     { NO_EXPR,     NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  50.     { NO_EXPR,     NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    MATRIX_EXPR, NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  51.     { NO_EXPR,     NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    NO_EXPR,       NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  52.     { POLY_EXPR, NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  53.     { NO_EXPR,   NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  54.     { NO_EXPR,   NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  55.     { NO_EXPR,   NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR } },
  56.  
  57.   { /* MULT */
  58.     { POLY_EXPR, NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    POLY_EXPR,   NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  59.     { NO_EXPR,     NUMERIC_EXPR, POINT_EXPR,   VECTOR_EXPR, NO_EXPR,    MATRIX_EXPR, NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  60.     { NO_EXPR,     POINT_EXPR,   NUMERIC_EXPR, NUMERIC_EXPR,NO_EXPR,    POINT_EXPR,  NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  61.     { NO_EXPR,     VECTOR_EXPR,  NUMERIC_EXPR, NUMERIC_EXPR,NO_EXPR,    VECTOR_EXPR, NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  62.     { NO_EXPR,     NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  63.     { POLY_EXPR, MATRIX_EXPR,  POINT_EXPR,   VECTOR_EXPR, NO_EXPR,    MATRIX_EXPR, CURVE_EXPR, SURFACE_EXPR,  NO_EXPR,     OLST_EXPR,   NO_EXPR },
  64.     { NO_EXPR,     NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    CURVE_EXPR,  NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  65.     { POLY_EXPR, NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    SURFACE_EXPR,NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  66.     { NO_EXPR,   NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  67.     { NO_EXPR,   NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    OLST_EXPR,   NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  68.     { NO_EXPR,   NO_EXPR,      NO_EXPR,      NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR } },
  69.  
  70.   { /* DIV */
  71.     { POLY_EXPR, NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  72.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  73.     { NO_EXPR,     NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  74.     { NO_EXPR,     NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  75.     { NO_EXPR,     NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  76.     { NO_EXPR,     NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  77.     { NO_EXPR,     NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  78.     { POLY_EXPR, NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  79.     { NO_EXPR,   NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  80.     { NO_EXPR,   NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  81.     { NO_EXPR,   NO_EXPR,      NO_EXPR,      NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR } },
  82.  
  83.   { /* POWER */
  84.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  85.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,         NO_EXPR,      NO_EXPR,    MATRIX_EXPR, NO_EXPR,    NO_EXPR,       STRING_EXPR, NO_EXPR,     NO_EXPR },
  86.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR,  VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  87.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR,  VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  88.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  89.     { NO_EXPR,     MATRIX_EXPR,  NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  90.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,       NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  91.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  92.     { NO_EXPR,   STRING_EXPR,  NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       STRING_EXPR, NO_EXPR,     NO_EXPR },
  93.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  94.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR } },
  95. };
  96.  
  97. /* The following table help to decide if the operand are legal for the given */
  98. /* operator. 1 entry for UNARMINUS. Each entry is a linear vector of length  */
  99. /* of number of object types:                             */
  100.  
  101. static IritExprType OverLoadMonadicTable[1][11] =
  102. /*  POLY_EXPR  NUMERIC_EXPR  POINT_EXPR  VECTOR_EXPR  PLANE_EXPR  MATRIX_EXPR  CURVE_EXPR  SURFACE_EXPR  STRING_EXPR  OLST_EXPR  CTLPT_EXPR */
  103. { /* UNARMINUS */
  104.   { POLY_EXPR, NUMERIC_EXPR, POINT_EXPR, VECTOR_EXPR, PLANE_EXPR, MATRIX_EXPR, CURVE_EXPR, SURFACE_EXPR, NO_EXPR,     NO_EXPR,   NO_EXPR }
  105. };
  106.  
  107. static int OverLoadTypeCheckAux(int Operator, IritExprType Right,
  108.                 IritExprType Left, IritExprType *Result);
  109. static IPObjectStruct *ConvSrfToPolys(ParseTree *Srf);
  110.  
  111. /*****************************************************************************
  112. *   Routine to perform type checking on the overloaded operators. Returns    *
  113. * TRUE if legal, and set Result to returned object type.             *
  114. *   Allows multiple types (I.e. VECTOR_EXPR | MATRIX_EXPR is legal input).   *
  115. *   Note output Result may be multiple types as well is a such case.         *
  116. *****************************************************************************/
  117. int OverLoadTypeCheck(int Operator, IritExprType Right, IritExprType Left,
  118.                             IritExprType *Result)
  119. {
  120.     int i, j, NumRightTypes, NumLeftTypes;
  121.     IritExprType TmpResult;
  122.  
  123.     /* Compute how many types are feasible here (input). */
  124.     for (i = 1, NumRightTypes = 0; i < ERROR_EXPR; i <<= 1)
  125.     NumRightTypes += (i & Right) != 0;
  126.     for (i = 1, NumLeftTypes = 0; i < ERROR_EXPR; i <<= 1)
  127.     NumLeftTypes += (i & Left) != 0;
  128.  
  129.     if (NumLeftTypes < 1 || NumRightTypes < 1)
  130.     return FALSE;
  131.     else if (NumLeftTypes == 1 && NumRightTypes == 1)
  132.     return OverLoadTypeCheckAux(Operator, Right, Left, Result);
  133.     else {
  134.     /* More than one type in the input - compute union of the output     */
  135.         /* types and return the union.                         */
  136.     *Result = 0;
  137.         for (i = 1; i < ERROR_EXPR; i <<= 1)
  138.         if ((i & Right) != 0)
  139.         for (j = 1; j < ERROR_EXPR; j <<= 1)
  140.             if ((j & Left) != 0)
  141.             if (OverLoadTypeCheckAux(Operator,
  142.                          (IritExprType) i,
  143.                          (IritExprType) j,
  144.                          &TmpResult))
  145.                 *Result |= TmpResult;
  146.  
  147.     return *Result != 0;
  148.     }
  149. }
  150.  
  151. /*****************************************************************************
  152. *   Routine to perform type checking on the overloaded operators. Returns    *
  153. * TRUE if legal, and set Result to returned object type.             *
  154. *   Assumes a single type (I.e. VECTOR_EXPR | MATRIX_EXPR is illegal input). *
  155. *****************************************************************************/
  156. static int OverLoadTypeCheckAux(int Operator, IritExprType Right,
  157.                 IritExprType Left, IritExprType *Result)
  158. {
  159.     int i, IRight, ILeft;
  160.  
  161.     for (i = 1, IRight = 0; i < Right; i <<= 1, IRight++);
  162.     for (i = 1, ILeft  = 0; i < Left;  i <<= 1, ILeft++);
  163.  
  164.     switch (Operator) {
  165.     case PLUS:
  166.     case MINUS:
  167.     case MULT:
  168.     case DIV:
  169.     case POWER:
  170.         *Result = OverLoadDiadicTable[Operator - OPERATORS_OFFSET]
  171.                      [IRight][ILeft];
  172.         return *Result != NO_EXPR;
  173.     case UNARMINUS:
  174.         *Result = OverLoadMonadicTable[0][IRight];
  175.         return *Result != NO_EXPR;
  176.     default:
  177.         IritFatalError("OverLoadTypeCheck: undefined operator");
  178.     }
  179.     return FALSE;                    /* Makes warning silent. */
  180. }
  181.  
  182. /*****************************************************************************
  183. *   Routine to evaluate    an monadic or diadic expression. It is assumed the   *
  184. * two operands are valid for the given expression - a test which can be made *
  185. * using OverLoadTypeCheck routine (see above). returned pointer to node with *
  186. * the result, NULL in case of error (should not happen actually).         *
  187. * Root holds the simple sub-expression (Root has the operator). PObj holds   *
  188. * all the currently defined objects available in the system. IError & CError *
  189. * will be set to relevant error if was one.                     *
  190. *****************************************************************************/
  191. ParseTree *OverLoadEvalOper(ParseTree *Root, ParseTree *TempR,
  192.         ParseTree *TempL, InptPrsrEvalErrType *IError, char *CError)
  193. {
  194.     int i,
  195.     OperReversed = FALSE;
  196.     char *Str;
  197.     RealType R;
  198.     ParseTree *Temp,
  199.     *RetVal = Root;
  200.     IPObjectStruct *TempLObj, *TempRObj;
  201.  
  202.     switch (Root -> NodeKind) {              /* Dies if undefined operator. */
  203.     case PLUS:
  204.     case MINUS:
  205.     case MULT:
  206.     case DIV:
  207.     case POWER:
  208.         if (TempR == NULL ||
  209.         TempL == NULL ||
  210.         TempR -> PObj == NULL ||
  211.         TempL -> PObj == NULL)
  212.         return NULL;                       /* Error! */
  213.         break;
  214.  
  215.     case UNARMINUS:
  216.         if (TempR == NULL || TempR -> PObj == NULL)
  217.         return NULL;                       /* Error! */
  218.         break;
  219.  
  220.     default:
  221.         IritFatalError("OverLoadEvalOper: Undefined operator");
  222.     }
  223.  
  224.     /* Make TempL be bigger, so we need handle less cases. */
  225.     if (Root -> NodeKind != UNARMINUS &&
  226.     ((int) TempR -> PObj -> ObjType) > ((int) TempL -> PObj -> ObjType)) {
  227.     Temp = TempR;
  228.     TempR = TempL;
  229.     TempL = Temp;
  230.  
  231.     OperReversed = TRUE;
  232.     }
  233.  
  234.     switch (Root -> NodeKind) {
  235.     case PLUS:
  236.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  237.         Root -> PObj = GenNUMValObject(TempL -> PObj -> U.R +
  238.                            TempR -> PObj -> U.R);
  239.         }
  240.         else if (IS_NUM_NODE(TempR) && IS_STR_NODE(TempL)) {
  241.         Root -> PObj = IPAllocObject("", IP_OBJ_STRING, NULL);
  242.         Str = Root -> PObj -> U.Str;
  243.         if (OperReversed) {
  244.             sprintf(Str, "%d", (int) (TempR -> PObj -> U.R));
  245.             strncpy(&Str[strlen(Str)],
  246.                 TempL -> PObj -> U.Str, LINE_LEN - 1);
  247.         }
  248.         else {
  249.             strncpy(Str, TempL -> PObj -> U.Str, LINE_LEN - 1);
  250.             sprintf(&Str[strlen(Str)], "%d",
  251.                 (int) (TempR -> PObj -> U.R));
  252.         }
  253.         }
  254.         else if (IS_PT_NODE(TempR) && IS_PT_NODE(TempL)) {
  255.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  256.         PT_ADD(Root -> PObj -> U.Vec,
  257.             TempL -> PObj -> U.Pt, TempR -> PObj -> U.Pt);
  258.         }
  259.         else if (IS_PT_NODE(TempR) && IS_VEC_NODE(TempL)) {
  260.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  261.         PT_ADD(Root -> PObj -> U.Vec,
  262.             TempL -> PObj -> U.Vec, TempR -> PObj -> U.Pt);
  263.         }
  264.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  265.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  266.         PT_ADD(Root -> PObj -> U.Vec,
  267.             TempL -> PObj -> U.Vec, TempR -> PObj -> U.Vec);
  268.         }
  269.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  270.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  271.                 MatAddTwo4by4(*Root -> PObj -> U.Mat,
  272.                   *TempL -> PObj -> U.Mat,
  273.                   *TempR -> PObj -> U.Mat);
  274.         }
  275.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  276.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  277.         TempLObj = ConvSrfToPolys(TempL);
  278.         TempRObj = ConvSrfToPolys(TempR);
  279.         Root -> PObj = BooleanOR(TempLObj, TempRObj);
  280.         if (Root -> PObj == NULL) {
  281.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  282.             UpdateCharError("Operator ", PLUS);
  283.             RetVal = NULL;
  284.         }
  285.         }
  286.         else if (IS_STR_NODE(TempR) && IS_STR_NODE(TempL)) {
  287.         Root -> PObj = IPAllocObject("", IP_OBJ_STRING, NULL);
  288.         Str = Root -> PObj -> U.Str;
  289.         sprintf(Str, "%s%s", TempL -> PObj -> U.Str,
  290.                      TempR -> PObj -> U.Str);
  291.         }
  292.         else if (IS_OLST_NODE(TempR) && IS_OLST_NODE(TempL)) {
  293.             Root -> PObj = AppendLists(TempL -> PObj, TempR -> PObj);
  294.         }
  295.         else if ((IS_CTLPT_NODE(TempR) || IS_CRV_NODE(TempR)) &&
  296.              (IS_CTLPT_NODE(TempL) || IS_CRV_NODE(TempL))) {
  297.         if (OperReversed)
  298.             Root -> PObj = MergeCurvesAndCtlPoints(TempR -> PObj,
  299.                                TempL -> PObj);
  300.         else
  301.             Root -> PObj = MergeCurvesAndCtlPoints(TempL -> PObj,
  302.                                TempR -> PObj);
  303.         }
  304.         else
  305.         RetVal = NULL;
  306.         break;
  307.     case MINUS:
  308.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  309.         Root -> PObj = GenNUMValObject(TempL -> PObj -> U.R -
  310.                            TempR -> PObj -> U.R);
  311.         }
  312.         else if (IS_PT_NODE(TempR) && IS_PT_NODE(TempL)) {
  313.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  314.         PT_SUB(Root -> PObj -> U.Vec,
  315.                TempL -> PObj -> U.Pt, TempR -> PObj -> U.Pt);
  316.         }
  317.         else if (IS_PT_NODE(TempR) && IS_VEC_NODE(TempL)) {
  318.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  319.         PT_SUB(Root -> PObj -> U.Vec,
  320.                TempL -> PObj -> U.Vec, TempR -> PObj -> U.Pt);
  321.         }
  322.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  323.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  324.         PT_SUB(Root -> PObj -> U.Vec,
  325.                TempL -> PObj -> U.Vec, TempR -> PObj -> U.Vec);
  326.         }
  327.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  328.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  329.                 MatSubTwo4by4(*Root -> PObj -> U.Mat,
  330.                   *TempL -> PObj -> U.Mat,
  331.                   *TempR -> PObj -> U.Mat);
  332.         }
  333.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  334.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  335.         TempLObj = ConvSrfToPolys(TempL);
  336.         TempRObj = ConvSrfToPolys(TempR);
  337.         Root -> PObj = BooleanSUB(TempLObj, TempRObj);
  338.         if (Root -> PObj == NULL) {
  339.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  340.             UpdateCharError("Operator ", MINUS);
  341.             RetVal = NULL;
  342.         }
  343.         }
  344.         else
  345.         RetVal = NULL;
  346.         break;
  347.     case MULT:
  348.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  349.         Root -> PObj = GenNUMValObject(TempL -> PObj -> U.R *
  350.                            TempR -> PObj -> U.R);
  351.         }
  352.         else if (IS_PT_NODE(TempR) && IS_PT_NODE(TempL)) {
  353.         Root -> PObj =
  354.             GenNUMValObject(DOT_PROD(TempL -> PObj -> U.Pt,
  355.                          TempR -> PObj -> U.Pt));
  356.         }
  357.         else if (IS_PT_NODE(TempR) && IS_VEC_NODE(TempL)) {
  358.         Root -> PObj =
  359.             GenNUMValObject(DOT_PROD(TempL -> PObj -> U.Vec,
  360.                          TempR -> PObj -> U.Pt));
  361.         }
  362.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  363.         Root -> PObj =
  364.             GenNUMValObject(DOT_PROD(TempL -> PObj -> U.Vec,
  365.                          TempR -> PObj -> U.Vec));
  366.         }
  367.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  368.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  369.                 MatMultTwo4by4(*Root -> PObj -> U.Mat,
  370.                    *TempL -> PObj -> U.Mat,
  371.                    *TempR -> PObj -> U.Mat);
  372.         }
  373.         else if (IS_NUM_NODE(TempR) && IS_PT_NODE(TempL)) {
  374.         Root -> PObj = IPAllocObject("", IP_OBJ_POINT, NULL);
  375.         PT_COPY(Root -> PObj -> U.Pt, TempL -> PObj -> U.Pt);
  376.         PT_SCALE(Root -> PObj -> U.Pt, TempR -> PObj -> U.R);
  377.         }
  378.         else if (IS_NUM_NODE(TempR) && IS_VEC_NODE(TempL)) {
  379.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  380.         PT_COPY(Root -> PObj -> U.Vec, TempL -> PObj -> U.Vec);
  381.         PT_SCALE(Root -> PObj -> U.Vec, TempR -> PObj -> U.R);
  382.         }
  383.         else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
  384.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  385.         MatScale4by4(*Root -> PObj -> U.Mat,
  386.                  *TempL -> PObj -> U.Mat,
  387.                  &TempR -> PObj -> U.R);
  388.         }
  389.         else if (IS_POLY_NODE(TempR) && IS_MAT_NODE(TempL)) {
  390.         Root -> PObj = GMTransformObject(TempR -> PObj,
  391.                            *TempL -> PObj -> U.Mat);
  392.         }
  393.         else if ((IS_MAT_NODE(TempR) && IS_CRV_NODE(TempL)) ||
  394.              (IS_MAT_NODE(TempR) && IS_SRF_NODE(TempL)) ||
  395.              (IS_MAT_NODE(TempR) && IS_OLST_NODE(TempL))) {
  396.         Root -> PObj = GMTransformObject(TempL -> PObj,
  397.                            *TempR -> PObj -> U.Mat);
  398.         }
  399.         else if (IS_VEC_NODE(TempR) && IS_MAT_NODE(TempL)) {
  400.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  401.         MatMultVecby4by4(Root -> PObj -> U.Vec,
  402.                  TempR -> PObj -> U.Vec,
  403.                  *TempL -> PObj -> U.Mat);
  404.         }
  405.         else if (IS_PT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  406.         Root -> PObj = IPAllocObject("", IP_OBJ_POINT, NULL);
  407.         MatMultVecby4by4(Root -> PObj -> U.Pt,
  408.                  TempR -> PObj -> U.Pt,
  409.                  *TempL -> PObj -> U.Mat);
  410.         }
  411.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  412.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  413.         TempLObj = ConvSrfToPolys(TempL);
  414.         TempRObj = ConvSrfToPolys(TempR);
  415.         Root -> PObj = BooleanAND(TempLObj, TempRObj);
  416.         if (Root -> PObj == NULL) {
  417.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  418.             UpdateCharError("Operator ", MULT);
  419.             RetVal = NULL;
  420.         }
  421.         }
  422.         else
  423.         RetVal = NULL;
  424.         break;
  425.     case DIV:
  426.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {  /* Numeric div. */
  427.         if (TempR -> PObj -> U.R != 0.0) {
  428.             Root -> PObj = GenNUMValObject(TempL -> PObj -> U.R /
  429.                            TempR -> PObj -> U.R);
  430.         }
  431.         else {
  432.             *IError = IE_ERR_DIV_BY_ZERO;
  433.             strcpy(CError, "/");
  434.             RetVal = NULL;
  435.         }
  436.         }
  437.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  438.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  439.         TempLObj = ConvSrfToPolys(TempL);
  440.         TempRObj = ConvSrfToPolys(TempR);
  441.         Root -> PObj = BooleanCUT(TempLObj, TempRObj);
  442.         if (Root -> PObj == NULL) {
  443.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  444.             UpdateCharError("Operator ", DIV);
  445.             RetVal = NULL;
  446.         }
  447.         }
  448.         else
  449.         RetVal = NULL;
  450.         break;
  451.     case POWER:
  452.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {/* Numeric power. */
  453.         Root -> PObj = GenNUMValObject(pow(TempL -> PObj -> U.R,
  454.                            TempR -> PObj -> U.R));
  455.         }
  456.         else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
  457.         /* Power MUST be integer in this case. */
  458.         i = (int) TempR -> PObj -> U.R;
  459.         if (!APX_EQ(i, TempR -> PObj -> U.R) || i < -1) {
  460.             *IError = IE_ERR_MAT_POWER;
  461.             strcpy(CError, "^");
  462.             RetVal = NULL;
  463.         }
  464.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  465.         if (i == -1) {             /* Generate the inverse matrix: */
  466.             if (!MatInverseMatrix(*TempL -> PObj -> U.Mat,
  467.                       *Root -> PObj -> U.Mat)) {
  468.             *IError = IE_ERR_MAT_POWER;
  469.             strcpy(CError, "^");
  470.             RetVal = NULL;
  471.             }
  472.         }
  473.         else {                  /* I must be positive integer. */
  474.             MatGenUnitMat(*Root -> PObj -> U.Mat);
  475.             while (i--)
  476.                 MatMultTwo4by4(*Root -> PObj -> U.Mat,
  477.                        *Root -> PObj -> U.Mat,
  478.                        *TempL -> PObj -> U.Mat);
  479.         }
  480.         }
  481.         else if (IS_NUM_NODE(TempR) && IS_STR_NODE(TempL)) {
  482.         Root -> PObj = IPAllocObject("", IP_OBJ_STRING, NULL);
  483.         Str = Root -> PObj -> U.Str;
  484.         if (OperReversed) {
  485.             sprintf(Str, GlblFloatFormat, TempR -> PObj -> U.R);
  486.             strcpy(&Str[strlen(Str)], TempL -> PObj -> U.Str);
  487.         }
  488.         else {
  489.             strcpy(Str, TempL -> PObj -> U.Str);
  490.             sprintf(&Str[strlen(Str)], GlblFloatFormat,
  491.                 TempR -> PObj -> U.R);
  492.         }
  493.         }
  494.         else if (IS_PT_NODE(TempR) && IS_PT_NODE(TempL)) {
  495.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  496.         GMVecCrossProd(Root -> PObj ->U.Vec,
  497.                    TempR -> PObj -> U.Pt,
  498.                    TempL -> PObj -> U.Pt);
  499.         }
  500.         else if (IS_PT_NODE(TempR) && IS_VEC_NODE(TempL)) {
  501.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  502.         GMVecCrossProd(Root -> PObj ->U.Vec,
  503.                    TempR -> PObj -> U.Pt,
  504.                    TempL -> PObj -> U.Vec);
  505.         }
  506.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  507.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  508.         GMVecCrossProd(Root -> PObj ->U.Vec,
  509.                    TempR -> PObj -> U.Vec,
  510.                    TempL -> PObj -> U.Vec);
  511.         }
  512.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  513.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  514.         TempLObj = ConvSrfToPolys(TempL);
  515.         TempRObj = ConvSrfToPolys(TempR);
  516.         Root -> PObj = BooleanMERGE(TempLObj, TempRObj);
  517.         if (Root -> PObj == NULL) {
  518.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  519.             UpdateCharError("Operator ", MINUS);
  520.             RetVal = NULL;
  521.         }
  522.         }
  523.         else if (IS_STR_NODE(TempR) && IS_STR_NODE(TempL)) {
  524.         Root -> PObj = IPAllocObject("", IP_OBJ_STRING, NULL);
  525.         Str = Root -> PObj -> U.Str;
  526.         sprintf(Str, "%s%s", TempL -> PObj -> U.Str,
  527.                      TempR -> PObj -> U.Str);
  528.         }
  529.         else
  530.         RetVal = NULL;
  531.         break;
  532.     case UNARMINUS:
  533.         if (IS_NUM_NODE(TempR)) {
  534.         Root -> PObj = GenNUMValObject(-TempR -> PObj -> U.R);
  535.         }
  536.         else if (IS_PT_NODE(TempR)) {
  537.         Root -> PObj = IPAllocObject("", IP_OBJ_POINT, NULL);
  538.         PT_COPY(Root -> PObj -> U.Pt, TempR -> PObj -> U.Pt);
  539.         PT_SCALE(Root -> PObj -> U.Pt, -1.0);
  540.         }
  541.         else if (IS_VEC_NODE(TempR)) {
  542.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  543.         PT_COPY(Root -> PObj -> U.Vec, TempR -> PObj -> U.Vec);
  544.         PT_SCALE(Root -> PObj -> U.Vec, -1.0);
  545.         }
  546.         else if (IS_PLANE_NODE(TempR)) {
  547.         Root -> PObj = IPAllocObject("", IP_OBJ_PLANE, NULL);
  548.         PLANE_COPY(Root -> PObj -> U.Plane, TempR -> PObj -> U.Plane);
  549.         for (i = 0; i < 4; i++)
  550.             Root -> PObj -> U.Plane[i] = -Root -> PObj -> U.Plane[i];
  551.         }
  552.         else if (IS_MAT_NODE(TempR)) {
  553.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  554.         R = -1.0;
  555.         MatScale4by4(*Root -> PObj -> U.Mat,
  556.                  *TempR -> PObj -> U.Mat,
  557.                  &R);
  558.         }
  559.         else if (IS_POLY_NODE(TempR)) {
  560.         Root -> PObj = BooleanNEG(TempR -> PObj);
  561.         }
  562.         else if (IS_CRV_NODE(TempR)) {
  563.         Root -> PObj = CurveReverse(TempR -> PObj);
  564.         }
  565.         else if (IS_SRF_NODE(TempR)) {
  566.         Root -> PObj = SurfaceReverse(TempR -> PObj);
  567.         }
  568.         else
  569.         RetVal = NULL;
  570.         break;
  571.     }
  572.     if (RetVal == NULL && *IError == IPE_NO_ERR) { /* Put general error msg: */
  573.     *IError = IE_ERR_TYPE_MISMATCH;
  574.     switch (Root -> NodeKind) {
  575.         case PLUS:
  576.         strcpy(CError, "Operator +");
  577.         break;
  578.         case MINUS:
  579.         strcpy(CError, "Operator -");
  580.         break;
  581.         case MULT:
  582.         strcpy(CError, "Operator *");
  583.         break;
  584.         case DIV:
  585.         strcpy(CError, "Operator /");
  586.         break;
  587.         case POWER:
  588.         strcpy(CError, "Operator ^");
  589.         break;
  590.         case UNARMINUS:
  591.         strcpy(CError, "Operator (unary) -");
  592.         break;
  593.     }
  594.     }
  595.  
  596.     return RetVal;
  597. }
  598.  
  599. /*****************************************************************************
  600. *   If given object is a surface, its polygonal representation object is     *
  601. * returned instead. Otherwise the given pointer is returned as is.           *
  602. *****************************************************************************/
  603. static IPObjectStruct *ConvSrfToPolys(ParseTree *Srf)
  604. {
  605.     IPObjectStruct *PObjPolys;
  606.     if (!IS_SRF_NODE(Srf))
  607.     return Srf -> PObj;
  608.  
  609.     if ((PObjPolys = AttrGetObjectObjAttrib(Srf -> PObj, "_polygons"))
  610.                                 == NULL) {
  611.         ComputeSurfacePolygons(Srf -> PObj);
  612.         PObjPolys = AttrGetObjectObjAttrib(Srf -> PObj, "_polygons");
  613.     }
  614.  
  615.     return PObjPolys;
  616. }
  617.